package com.netty.demo.server.utils;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.netty.demo.server.ApplicationUtil;
import com.netty.demo.server.config.FileScanPathConfig;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 文件扫描相关功能
 *
 * @author Administrator 余秀良
 * @version 1.0
 * <p>date: 2019年09月19日  19:47 </p>
 * <p>address: 四川成都 </p>
 */
@SuppressWarnings("ALL")
@Slf4j
public class FileScanUtil {
    /**
     * 开始执行扫描任务
     *
     * @return 返回 xml文件内容 格式为：List< Map< String, Object>>
     * @author 余秀良
     * @version 1.0
     * <p>  date: 2019 - 09 - 20  16:59    </p>
     * <p>  address: 四川成都  </p>
     */
    public static List<Map<String, Object>> start() {
        List<Map<String, Object>> dataList = null;
        try {
            unzip();
            dataList = parserxml();
        } catch (Exception e) {
            log.error("文件扫描出错 \n {} \n {}", e.getMessage(), e.getLocalizedMessage());
            e.printStackTrace();
            return null;
        }
        return dataList;
    }

    /**
     * 解压 zip
     */
    private static void unzip() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), new ThreadFactoryBuilder().setNameFormat("unzip-thread-pool-%d").build(), new CallerRunsPolicy());
        try {
            FileScanPathConfig config = ApplicationUtil.getApplicationContext().getBean(FileScanPathConfig.class);
            File filePath = new File(config.getScanPath());
            if (filePath.exists()) {
                File[] fileArray = filePath.listFiles();
                if (fileArray != null) {
                    for (File file : fileArray) {
                        boolean archiveFile = ZipUtil.isZipFile(file);
                        if (archiveFile) {
                            CompletableFuture.runAsync(() -> {
                                //注意 解压的时候设置 存放解压文件的目录
                                ZipUtil.unZip(file.getPath(), config.getUnzipPath());
                            }, threadPoolExecutor);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("unzip 方法出错 \n {} \n {}", e.getMessage(), e.getLocalizedMessage());
            e.printStackTrace();
        } finally {
            threadPoolExecutor.shutdown();
        }
    }

    /**
     * 解析 xml
     */
    private static List<Map<String, Object>> parserxml() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 10, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), new ThreadFactoryBuilder().setNameFormat("parserxml-thread-pool-%d").build(), new CallerRunsPolicy());
        List<Map<String, Object>> dataList = new LinkedList<>();
        try {
            FileScanPathConfig config = ApplicationUtil.getApplicationContext().getBean(FileScanPathConfig.class);
            //注意 这里设置解压后的目录
            File filePath = new File(config.getUnzipPath());
            if (filePath.exists()) {
                File[] fileArray = filePath.listFiles();
                if (fileArray != null) {
                    List<CompletableFuture<List<Map<String, Object>>>> completableFutureList = new LinkedList<>();
                    for (File file : fileArray) {
                        if (file.getName().endsWith(".xml")) {
                            CompletableFuture<List<Map<String, Object>>> listCompletableFuture = CompletableFuture.supplyAsync(() -> ParserXmlUtil.dom4jXmlToList(file.getPath()), threadPoolExecutor);
                            completableFutureList.add(listCompletableFuture);
                        }
                    }
                    dataList = completableFutureList.stream().map(CompletableFuture::join).flatMap(mapList -> mapList.stream()).collect(Collectors.toList());
                }
            }
        } catch (Exception e) {
            log.error("parserxml 方法出错 \n {} \n {}", e.getMessage(), e.getLocalizedMessage());
            e.printStackTrace();
        } finally {
            threadPoolExecutor.shutdown();
        }
        return dataList;
    }

}
